

                     L                ZZZZZZ         RRRRR           SSSSS
                     L                    Z          R    R         S
                     L          aaa      Z      aaa  R    R  u   u  S
                     L            a     Z         a  RRRRR   u   u  SSSSS
               XX    L         aaaa    Z       aaaa  R    R  u   u       S
              XXXX   L        a   a   Z       a   a  R    R  u   u       S
             XXXXXX  LLLLLLL  aaaaa  ZZZZZZZ  aaaaa  R    R  uuuuu  SSSSSS
             XXXXXX       
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
             XXXXXX
             XXXXXX
              XXXX        proudly presents his 33.Cracking Tutorial (22.12.1999)
               XX      Adding a section and enarging the last section of a PE file

I.   Introduction
I.1  The tools
II.  The essay
II.1 The CrackMe
II.2 DocClear
III. BTW

I.   Introduction
     Yesterday someone asked in IRC (#cracking4newbies) how to add a section to a PE file and 
     today I saw the another request at +Sandmans Newbie Forum (crfb.cjb.net) and I had my last
     school day today and can't start to idle at 11am ;) So I decided to write a small tut how
     to manage this. 

I.1  The tools
     SoftIce (I have v3.25)
     HexWorkshop
     Procdump
     Interrupter
     A PE analyzer (I use my own one, but you should get a good one)
     Good music: I listen currently to the song "Raventhrone" by "Raventhrone" (raventhrone.com)

II.  The essay
II.1 Enlarging the last section

     At first we need a target: I have coded a special crackme for this one which I packed with
     UPX 0.84 after it. It is very simple: If you enter "Test" as serial you get the "Your serial
     is correct" message, else "Your serial is wrong". We will try to patch it to write the 
     correct serial to the dialog caption if the user enters a wrong serial.

     After it is packed with UPX we will load it in Procdump and see that the PE editor reveals
     this:

     Sectionname  Virtual Size  Virtual Offset  Raw Size  Raw Offset  Characteristics
        UPX0        00005000       00001000     00000000  000000400       E0000080
        UPX1        00001000       00006000     00000400  000000400       E0000040
        .rsrc       00001000       00007000     00000200  000000800       C0000040

     I won't explain the function of the sections and the values of the characteristics. If you
     want to have additional knowledge about them, please consult pe.txt.

     Our first goal is to enlarge the last section in order to put the data we need for the patch
     there. UPX is an exception of the standard packers around, as UPX wraps the existing 
     sections and makes it's own sections to be the first and not the last as many other packers.
     So here we gotta enlarge the .rscr section which doesn't make a difference to enlarging
     a packed section. This info is just for the record ;)

     btw: You can add and modify complete section with Procdump, but one day a situation might
     appear where you gotta learn how to do it manually, so please go on, dear reader :)

     The first thing we have to do is finding the last section in the EXE file AND in memory. 
     This is plain and simple, as the values of Raw Offset (file) and Virtual Offset (memory)
     just show these places. So, the .rscr section starts - in the file - at offset 800h. Here
     it is:

     00000800 0000 0000 0000 0000 0000 0000 0000 0100 ................
     00000810 0500 0000 1800 0080 0000 0000 0000 0000 ................
     00000820 0000 0000 0100 0000 5800 0080 3000 0080 ........X...0...
     00000830 0000 0000 0000 0000 0000 0000 0000 0100 ................
     00000840 0904 0000 4800 0000 7040 0000 4401 0000 ....H...p@..D...
     00000850 0000 0000 0000 0000 0700 4D00 4100 4900 ..........M.A.I.
     00000860 4E00 4400 4C00 4700 0000 0000 0000 0000 N.D.L.G.........
     00000870 0000 0000 0000 0000 0000 0000 C070 0000 .............p..
     00000880 AC70 0000 0000 0000 0000 0000 0000 0000 .p..............
     00000890 CD70 0000 B870 0000 0000 0000 0000 0000 .p...p..........
     000008A0 0000 0000 0000 0000 0000 0000 D870 0000 .............p..
     000008B0 E670 0000 0000 0000 F670 0000 0000 0000 .p.......p......
     000008C0 4B45 524E 454C 3332 2E44 4C4C 0055 5345 KERNEL32.DLL.USE
     000008D0 5233 322E 646C 6C00 0000 4C6F 6164 4C69 R32.dll...LoadLi
     000008E0 6272 6172 7941 0000 4765 7450 726F 6341 braryA..GetProcA
     000008F0 6464 7265 7373 0000 5365 7446 6F63 7573 ddress..SetFocus
     00000900 0000 0000 0060 0000 0C00 0000 2232 0000 .....`......"2..
     00000910 0000 0000 0800 0000 0000 0000 0000 0000 ................
     00000920 0000 0000 0000 0000 0000 0000 0000 0000 ................
     00000930 0000 0000 0000 0000 0000 0000 0000 0000 ................
     00000940 0000 0000 0000 0000 0000 0000 0000 0000 ................
     00000950 0000 0000 0000 0000 0000 0000 0000 0000 ................
     00000960 0000 0000 0000 0000 0000 0000 0000 0000 ................
     00000970 0000 0000 0000 0000 0000 0000 0000 0000 ................
     00000980 0000 0000 0000 0000 0000 0000 0000 0000 ................
     00000990 0000 0000 0000 0000 0000 0000 0000 0000 ................
     000009A0 0000 0000 0000 0000 0000 0000 0000 0000 ................
     000009B0 0000 0000 0000 0000 0000 0000 0000 0000 ................
     000009C0 0000 0000 0000 0000 0000 0000 0000 0000 ................
     000009D0 0000 0000 0000 0000 0000 0000 0000 0000 ................
     000009E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
     000009F0 0000 0000 0000 0000 0000 0000 0000 0000 ................

     You wonder why I know how long it is? Guess what's the value of Raw Size ;)
     The value of Virtual Size (memory) differs from the one of Raw Size (file) because PE files
     must have a certain section alignment which differs on disc and in memory and to get this
     alignment when the Raw Size is smaller some 00-Bytes are added to the section in memory
     to make it fit the alignment.

     So, here's the deal: We want to patch the file in a way that it displays the sentence
     "The correct serial is Test" if the user enters a wrong serial. To achieve this we will
     redirect the code from the check of the serial to our enlarged section and then we enter
     some code there and jump back to the "original" part of the file.

     The first thing we got to do is enlarging the section. From now on we will do *everything*
     manually. No more Procdump allowed ;) To know how to enlarge the section we have to find 
     where this info is stored in the file. It is very easy to find. Just open it in your 
     favourite Hexeditor and scroll down from the beginning of the file until you see the 
     section names. Of course there is a more "sophisticated" way to find the section info, but
     this one is surely the quickest. You will find this:

     000001B0 0000 0000 0000 0055 5058 3000 0000 0000 .......UPX0.....
     000001C0 5000 0000 1000 0000 0000 0000 0400 0000 P...............
     000001D0 0000 0000 0000 0000 0000 0080 0000 E055 ...............U
     000001E0 5058 3100 0000 0000 1000 0000 6000 0000 PX1.........`...
     000001F0 0400 0000 0400 0000 0000 0000 0000 0000 ................
     00000200 0000 0040 0000 E02E 7273 7263 0000 0000 ...@....rsrc....
     00000210 1000 0000 7000 0000 0200 0000 0800 0000 ....p...........
     00000220 0000 0000 0000 0000 0000 0040 0000 C000 ...........@....

     When you look at .rsrc you will see exactly the values we got from Procdump, so we would
     not even have to use Procdump (Pay attention that the high-bytes and low-bytes are turned
     around, so if you see 0010h it is not 10h=16d, but 1000h=4096d). Now just find the 200h
     from Procdump (00 02) here. Change it to 230h (30 02) and go to the end of the file. If you
     want extended information about the values that make up a section description: PE.TXT

     When you are at the end of the file you got to add 30h = 64d Bytes. This should be much more
     than enough, but better too many bytes, than too few.

     Now it's time to find the address we need to patch: 
     I know what I have coded and I know that you can easily find the important passage, too,
     so I won't explain how to find it. I will choose the passage where the "Wrong" gets
     written to the edit field. 

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:004010F9(U)
     |

     * Possible StringData Ref from Code Obj ->"Wrong"
                                       |
     :00401102 68FB104000              push 004010FB
     :00401107 68EB030000              push 000003EB
     :0040110C FF7508                  push [ebp+08]

     * Reference To: USER32.SetDlgItemTextA, Ord:0228h
                                       |
     :0040110F E81C000000              Call 00401130
     :00401114 C9                      leave
     :00401115 C20400                  ret 0004

     My intention is to remove the first push and put a jump there which leads to the
     code we will add in the next part. We gotta find this part first, as we know where it is
     in the file, but not where it is in memory. But don't worry, it's cheap. You remember that
     .rsrc at Virtual Offset 7000 starts? I hope so ;) Now we know that the Raw Size of the
     section was 200h bytes. We added something, so our stuff should start at offset 7200h.
     To make it sure, use your hexeditor and put "Hope" at offset A00h in the file (where we
     added 30h bytes. When you break on SetDlgItemTextA in SICE and try to register it, look
     at 407200. If you find "Hope" everything's OK, if not you made a mistake. 407200? Why not
     7200? You got to add the ImageBase of the EXE file. If you want detailed information:
     consult PE.txt, if not let me just say this: In 99,9% of all Win9X EXE files, 400000 is the
     Imagebase. 

     Now, the next part: We have to replace the push instruction - for this purpose we use SICE:
     I changed the line
     :00401102 68FB104000              push 004010FB
     to
     :00401102 E9F9600000              jmp 407200

     btw: it would be million times better, if you would use the existing SetDlgItemTextA routine
     but then the enlarging of the section would have no use ;)

     Uhm, btw: How do we patch the file? It's packed! Well, I believe we have to enlarge the
     section again ;) Add 10h bytes to the section characteristics and to the end of the file.
     I won't explain it this time, as it is *completely* the same as above.

     When you have done it, load the packed file into W32Dasm and scroll down to the end. You 
     will see this:

     * Referenced by a (U)nconditional or (C)onditional Jump at Address:
     |:0040632F(C)
     |
     :0040636B 61                      popad
     :0040636C E98FACFFFF              jmp 00401000

     This is the jump that is taken when UPX has finished unpacking. We have to change it to
     jmp 407230 which is the offset of the second part of the section we added. To get the
     valid opcode for it use SICE in combination with my tool "Interrupter". It puts an CCh
     opcode at the entry point of every PE file and you can breakpoint on it using "bpint 03". 
     Then you need to replace the byte that was overwritten by using "e eip XX" in SICE where
     XX is the number Interrupter returns you. Then "bpx 40636C" and when SICE breaks, enter
     "a eip" and choose "jmp 407230" to change the instruction and get the opcode: E9BF0E0000.
     To make the patch permanent use your HexEditor. Search for E98FACFFFF and replace it by
     E9BF0E0000.

     Now the next things: We gotta exchange the push-instruction (the one from SetDlgItemTextA)
     to "jmp 407200". This is done by adding code that patches the unpacked code. The following
     instructions are to be added to the second part of our enlarged section to convert the push
     to a jump:

     mov dword ptr [401102], 0060F9E9 ;; CONVERT PUSH TO JMP
     mov byte ptr [401106], 00 ;; SAME
     jmp 401000 ;; JUMP TO REAL ENTRYPOINT

     The opcodes for this are:
     C70502114000E9F96000
     C6050611400000
     E9BA9DFFFF

     Now it's time to add the bytes which displays "The correct serial is Test" (btw: add 
     this string with your hexeditor to offset A15h). To achieve this, break on the line which
     jumps to 407200. When you are there take this jump and then we gotta add the following
     instructions:

     push 407215
     jmp 401107

     This pushes the string and then jumps back to the other two pushes and the call to 
     SetDlgItemTextA. I know myself that just patching the first push to make it push the
     added string would be enough, but then you would have missed the fun redirecting part ;)

     Well, the opcodes for the instructions above are:
     6815724000
     E9FD9EFFFF

     Add them to your file at the beginning of the enlarged section at offset A00h.

     Disable all breakpoints and run the EXE file.
     When you run the file now, you will most probably get an error message ;) This is because
     you surely did not replace the CCh at the beginning of the file which was put there by
     Interrupter. Replace offset 620h by 60h and everything should work. At least here it works,
     if it doesn't work at your PC, please check everything and retry. You can also compare my
     enlarged.exe with your exe file. 

II.2 Adding a new section:
     Now, I made a copy of enlarged.exe to demonstrate how adding a section to an exe file works.
     The file now is called adding.exe and the first thing we have to do is to restore the old
     values of the .rsrc section, that means: Change back the size of the section from 250h
     to 200h. 

     You have to know that a PE file has the information how many sections the file contains
     stored in its header definition. This info is stored at offset PEStart+6 which is here:

     000000C0 5045 0000 4C01 0300 1FC0 6038 0000 0000 PE..L.....`8....

     You can find out where the PE starts by looking at offset 3Ch of the EXE file or by 
     searching for 50450000, the bytes every PE header start with.

     So, we can see that there are three sections to be found in this EXE file. Don't hesitate
     and increase this value by 1. Now go to the section definitions and add a new section 
     called "Tutorial". You gotta know that every section definition is 28h bytes long. So you
     have to start writing "Tutorial" at offset 230h. It will look like this:

     00000200 0000 0000 4000 00E0 2E72 7372 6300 0000 ....@....rsrc...
     00000210 0010 0000 0070 0000 0002 0000 0008 0000 .....p..........
     00000220 0000 0000 0000 0000 0000 0000 4000 00C0 ............@...
     00000230 5475 746F 7269 616C 0000 0000 0000 0000 Tutorial........

     Watch out that a section name must have max of 8 chars.

     The next thing we have to do is deciding which Virtual Offset/Virtual Size/Raw Offset and
     Raw Size our section should have. To decide this, we need the following values:

     Virtual offset of formerly last section (.rsrc): 7000h
     Virtual size of formerly last section (.rsrc): 1000h
     Raw offset of formerly last section (.rsrc): 800h
     Raw size of formerly last section (.rsrc): 200h
     Section Alignment: 1000h
     File Alignment: 200h

     Section Alignment and File Alignment are the minimum sizes of a section in the memory and
     in the file. So, we have to give our new section at least a section alignment of 1000h
     and a file alignment of 200h. For further documentation: Pe.txt
     The Raw Offset of the section is just the offset in the file, which is A00h like we have
     chosen in the first part of this essay, to get the Virtual Offset of our section we
     have to calculate this: VIRTUAL SECTION OF .rsrc + VIRTUAL SIZE OF .rsrc = 8000h. Luckily
     it perfectly fits to the section Alignment (8000 MOD 1000 = 0) and we can choose 8000h
     for our Virtual Offset. If VIRTUAL SECTION OF .rsrc + VIRTUAL SIZE OF .rsrc would be 8200h
     for example, we needed to take 9000h as this is the next value which MOD SECTION ALIGNMENT
     is 0. So, let's fill the desription of our section:

     00000230 5475 746F 7269 616C 0010 0000 0080 0000 Tutorial........
     00000240 0002 0000 000A 0000 0000 0000 0000 0000 ................
     00000250 0000 0000 4000 00C0 0000 0000 0000 0000 ....@...........

     Here everything is added and has its order. 

     When you start the prog now, it will crash, as the "old" jump at the end of the unpacking
     section is still active. We gotta change

     :0040636C E9BF0E0000              jmp 00407230
     to
     :0040636C E9BF1CFFFF              jmp 00408030

     If you execute it, it will still crash and when you look at 408000 in memory you will see
     that is is not initialized. There's a small thing we have forgotten: It is called "Image
     Base". Here a copy/paste from PE.txt

     The next entry is a 32-bit-value giving the preferred (linear) load
     address ('ImageBase') of the entire binary, including all headers. This
     is the address (always a multiple of 64 KB) the file has been relocated
     to by the linker; if the binary can in fact be loaded to that address,
     the loader doesn't need to relocate the file again, which is a win in
     loading time.
     The preferred load address can not be used if another image has already
     been loaded to that address (an "address clash", which happens quite
     often if you load several DLLs that are all relocated to the linker's
     default), or the memory in question has been used for other purposes
     (stack, malloc(), uninitialized data, whatever). In these cases, the
     image must be loaded to some other address and it needs to be relocated
     (see 'relocation directory' below). This has further consequences if the
     image is a DLL, because then the "bound imports" are no longer valid,
     and fixups have to be made to the binary that uses the DLL - see 'import
     directory' below.

     Pretty hard to get? Whatever, to make it short. The ImageBase must be - at least - the size
     of the last Virtual Offset + Virtual Size which is 9000h in our case. You will find the
     important data at offset 110h (PEStart+50h). Change it from 0080 to 0090 and restart.
    
     Now you got to change the jump at offset A41 (jmp 401030) to "jmp 401000" (E9BA8FFFFF) and
     the 

     mov dword ptr [401102], 0060F9E9 ;; CONVERT PUSH TO JMP
     mov byte ptr [401106], 00 ;; SAME
     jmp 401000 ;; JUMP TO REAL ENTRYPOINT

     to

     mov dword ptr [401102], 006EF9E9 ;; CONVERT PUSH TO JMP
     mov byte ptr [401106], 00 ;; SAME
     jmp 401000 ;; JUMP TO REAL ENTRYPOINT

     Watch out that you have to recalculate ALL jumps and the "push 407215" now. When you have
     done it, replace the CCh at the beginning of the file again. If it works: well done; if not:
     compare my file adding.exe to the one you created.

III. BTW
     So guys, that's all. If you want additional info about the PE format, please read PE.TXT
     at least 25 times. I hope you learned something from this essay (at least how to enlarge
     and add a section ;)

     Greetings go to: +Sandman, Acid Burn, alpine, Blind Angel, Borna Janes,
     Carpathia, CrazyKnight, DEATH, DEZM, dimwitz, DnNuke, duelist, Eternal Bliss,
     Fravia+, Iczelion, Jordan, KnowledgeIsPower, Knotty, Lucifer48, MisterE,
     Neural Noise, noos, Prof.X, R!SC, rubor, Shadow, SiG, tC, The AntiXryst, The
     Hobgoblin, TORN@DO, ultraschall, viny, Volatility, wAj, _y and all the guys
     I forget and I'll add next time.

     Mail: lazarus_hf@hotmail.com
     URL: hello.to/lazarus
     #Efnet: #cracking4newbies, #learn2crack (German)